<?php
	abstract class S3andSDBModel extends SDBModel
	{
		protected $_s3;
		protected $_binary_content;
		protected $_binary_info;

		public function __construct()
		{
			parent::__construct();
			$this->_s3 = Zend_Registry::get('s3'); 
			$this->_binary_content = null;
			$this->_binary_info = array();
		}
		
		public function __destruct()
		{
			unset($this->_s3);
			unset($this->_binary_content);
			unset($this->_binary_info);
			parent::__destruct();
		}
		
		public function setBucket($bucket)
		{
			$this->_attributes['bucket'] = $bucket;
		}

		public function getBucket()
		{
			return $this->_attributes['bucket'];
		}

		// throws db exception
		public function load($id)
		{
			parent::load($id);
			$this->setBinaryInfoFromAttrs();
		}

		public function save($i = 0)
		{
			if (sizeof($this->_binary_info > 0))
			{
				# generate an id if needed
				if (!isset($this->_id))
					$this->_id = ($i > 0) ? CommonGenerator::generateUniqueId($i) 
						: CommonGenerator::generateUniqueId();

				# generate a filename
				$content_type = split(';', $this->_binary_info['headers']['Content-Type']);
				$this->_attributes['filename'] = 
					CommonGenerator::generateFilenameFromContentType($this->_id, $content_type[0]);

				# attempt to save binary and db information
				if ($this->_binary_content != null)
				{
					if ($this->_s3->putObject($this->_binary_content, 
						$this->_attributes['bucket'], $this->_attributes['filename'], 
						$this->_binary_info['access'], array($this->_binary_info['headers']['Content-Type']), 
						$this->_binary_info['headers']['Content-Type']))
					{
						parent::save($i);
					}
					else
					{
						# failed to put media into storage! log it and throw an exception
						$msg = "Failed to save to S3 storage.  Data dump to follow...";
						$this->_logger->log('(' . get_class($this) . ') ' . $msg, Zend_Log::ERR);
						$this->_logger->log('(' . get_class($this) . ') ' . print_r($this->_binary_info, true), Zend_Log::ERR); 
						$this->_logger->log('(' . get_class($this) . ') ' . print_r(base64_encode($this->_binary_content), true), 
							Zend_Log::ERR); 
						$this->_logger->log('(' . get_class($this) . ') ' . print_r($this->_attributes, true), Zend_Log::ERR); 

						$ex_msg = "Failed to store media from user_id {$this->_attributes['user_id']}"
							. " with filename '{$this->_attributes['filename']}' and bucket id "
							. "'{$this->_attributes['bucket']}' to Amazon S3 storage. "
							. ' Might just be a problem with S3. Data dump to follow...';
						throw new S3andSDBModelException($ex_msg, 3);
					}
				}
				else
				{
						parent::save($i);
				}
			}
			else
			{
					# failed to put media into storage! log it and throw an exception
					$msg = "Failed to save to S3 storage.  Binary content or info not set. Data dump to follow...";
					$this->_logger->log('(' . get_class($this) . ') ' . $msg, Zend_Log::ERR);
					$this->_logger->log('(' . get_class($this) . ') ' . print_r($this->_binary_info, true), Zend_Log::ERR); 
					$this->_logger->log('(' . get_class($this) . ') ' . print_r(base64_encode($this->_binary_content), true), 
						Zend_Log::ERR); 
					$this->_logger->log('(' . get_class($this) . ') ' . print_r($this->_attributes, true), Zend_Log::ERR); 

					$ex_msg = "Failed to store media from user_id {$this->_attributes['user_id']}"
						. " with filename '{$this->_attributes['filename']}' and bucket id "
						. "'{$this->_attributes['bucket']}' to Amazon S3 storage. "
						. ' Might just be a problem with S3. Data dump to follow...';
					throw new S3andSDBModelException($ex_msg, 3);
			}
		}
		
		public function delete()
		{
			if (isset($this->_id))
			{
				if(!$this->_s3->deleteObject($this->_attributes['bucket'], 
					$this->_attributes['filename']))
				{
					# failed to delete media from storage! log it and throw an exception
					$msg = "Failed to delete from S3 storage.  Data dump to follow...";
					$this->_logger->log('(' . get_class($this) . ') ' . $msg, Zend_Log::ERR);
					$this->_logger->log('(' . get_class($this) . ') ' . print_r($this->_binary_info, true), Zend_Log::ERR); 
					$this->_logger->log('(' . get_class($this) . ') ' . print_r(base64_encode($this->_binary_content), true), 
						Zend_Log::ERR); 
					$this->_logger->log('(' . get_class($this) . ') ' . print_r($this->_attributes, true), Zend_Log::ERR); 

					$ex_msg = "Failed to delete media from user_id {$this->_attributes['user_id']}"
						. " with filename '{$this->_attributes['filename']}' and bucket id "
						. "'{$this->_attributes['bucket']}' to Amazon S3 storage. "
						. ' Might just be a problem with S3. Data dump to follow...';
					throw new S3andSDBModelException($ex_msg, 3);
				}
				parent::delete();
			}
		}

		public function setBinaryInfo($binary_content, $binary_info)
		{
			$this->_binary_content = $binary_content;
			$this->_binary_info = $binary_info;
			$this->_attributes['content-type']= $this->_binary_info['headers']['Content-Type'];
			$this->_attributes['access'] = $this->_binary_info['access'];
			$this->_saved = false;
		}
		
		public function clearObject()
		{
			$this->_binary_content = null;
			$this->_binary_info = array();
			parent::clearObject();
		}
		
		public function getUrl()
		{
			if ($this->_saved == true)
				$url = $this->_config->aws->s3->url . '/' . $this->_attributes['bucket']
					. '/' . $this->_attributes['filename'];
			else
				$url = null;
			
			return $url;
		}

		protected function setBinaryInfoFromAttrs()
		{
			$this->_binary_info = array(
				'access' => (isset($this->_attributes['access']) ? $this->_attributes['access'] : S3::ACL_PUBLIC_READ),
				'headers' => array('Content-Type' => $this->_attributes['content-type']),
			);
		}
	}
